package com.wesley.prototype;


import java.io.*;

/**
 * <h1>概述</h1>
 * <p>详述</p>
 *
 * @Date: 2021/8/12
 */
public class DeepClone implements Serializable, Cloneable {

    private String name;

    private DeepCloneTarget deepCloneTarget;

    public DeepClone() {
    }

    public DeepClone(String name, DeepCloneTarget deepCloneTarget) {
        this.name = name;
        this.deepCloneTarget = deepCloneTarget;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public DeepCloneTarget getDeepCloneTarget() {
        return deepCloneTarget;
    }

    public void setDeepCloneTarget(DeepCloneTarget deepCloneTarget) {
        this.deepCloneTarget = deepCloneTarget;
    }

    /**
     * 方式1， 重写克隆方法
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 基本数据类型的克隆
        Object deep = super.clone();
        // 引用的克隆
        DeepClone deepClone = (DeepClone) deep;
        deepClone.deepCloneTarget = (DeepCloneTarget) deepClone.deepCloneTarget.clone();
        return deepClone;
    }


    /**
     * <h1>深拷贝，序列化方式（推荐）</h1>
     *
     * @return {@link Object}
     * @author wei.xin
     * @date 2021/8/12
     */
    public Object deepClone() {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;

        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;

        try {
            // 序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            // 当前对象以流的方式输出
            oos.writeObject(this);

            // 反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            // 读取对象
            return ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                assert bos != null;
                bos.close();
                assert oos != null;
                oos.close();
                assert bis != null;
                bis.close();
                assert ois != null;
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
